www.gusucode.com > VC++ 编写软件自动升级服务源代码 > VC++ 编写软件自动升级服务源代码/gusucode/updater_src0.8.1.6/RestoreInfo.cpp

    /********************************************************************
	created:	2005/03/02
	created:	2:3:2005   13:29
	filename: 	RestoreInfo.cpp
	file path:	Updater
	file base:	RestoreInfo
	file ext:	cpp
	author:		Geert van Horrik
	
	purpose:	
*********************************************************************/

//*********************************************************************
// INCLUDES
//*********************************************************************

#include "stdafx.h"
#include "Updater.h"
#include "RestoreInfo.h"
#include "Sections.h"

//*********************************************************************
// INITIALISATION
//*********************************************************************

std::auto_ptr<CRestoreInfo> CRestoreInfo::sm_inst;

//*********************************************************************
// CONSTRUCTOR & DESTRUCTOR
//*********************************************************************

CRestoreInfo::CRestoreInfo()
{
	// Set some values
	m_iSectionCount = 0;
	m_iRestoreActionCount = 0;
}

//*********************************************************************
// PUBLIC FUNCTIONS
//*********************************************************************

CRestoreInfo * CRestoreInfo::Instance()
{
	if(sm_inst.get() == 0)
		sm_inst = auto_ptr<CRestoreInfo>(new CRestoreInfo);
	return sm_inst.get();

	/* FOLLOWING CODE WORKS ONLY IN VC7
	if(sm_inst.get() == 0)
		sm_inst.reset(new CRestoreInfo);
	return sm_inst.get();
	*/
}

//=====================================================================

CRestoreActionBase * CRestoreInfo::GetAction(int iIndex)
{
	// Return action
	return m_arrRestoreActions[iIndex];
}

//=====================================================================

void CRestoreInfo::AddAction(CRestoreActionBase * pAction)
{
	// Declare variables
	bool bValid = false;

	// Check what type of action to add
	switch (pAction->GetType())
	{
	case RESTOREACTION_COPY:
		if (IsValidActionCopy(pAction))
			bValid = true;
		break;

	case RESTOREACTION_DELETE:
		if (IsValidActionDelete(pAction))
			bValid = true;
		break;

	case RESTOREACTION_REGISTRY:
		// Always perform registry actions
		bValid = true;
		break;

	case RESTOREACTION_UNREGISTER:
		// Always perform unregister actions
		bValid = true;
		break;
	}	

	// Add action to array
	if (bValid)
		m_arrRestoreActions[m_iRestoreActionCount++] = pAction;
}

//=====================================================================

void CRestoreInfo::AddActionCopy(CString sOldLocation, CString sNewLocation)
{
	// Set up information
	CRestoreActionBase * pAction = new CRestoreActionCopy(sOldLocation, sNewLocation);

	// Add to array
	AddAction(pAction);
}

//=====================================================================

void CRestoreInfo::AddActionDelete(CString sLocation)
{
	// Set up information
	CRestoreActionBase * pAction = new CRestoreActionDelete(sLocation);
	
	// Add to array
	AddAction(pAction);
}

//=====================================================================

void CRestoreInfo::AddActionRegistry(CString sKey, CString sValue)
{
	// Set up information
	CRestoreActionBase * pAction = new CRestoreActionRegistry(sKey, sValue);
	
	// Add to array
	AddAction(pAction);
}

//=====================================================================

void CRestoreInfo::AddActionUnregister(CString sFile)
{
	// Set up information
	CRestoreActionBase * pAction = new CRestoreActionUnregister(sFile);
	
	// Add to array
	AddAction(pAction);
}

//=====================================================================

int CRestoreInfo::GetActionCount()
{
	// Return value
	return m_iRestoreActionCount;
}

//=====================================================================

void CRestoreInfo::SetVersion(CString sVersion)
{
	// Set value
	m_sVersion = sVersion;
}

//=====================================================================

CString CRestoreInfo::GetVersion()
{
	// Return value
	return m_sVersion;
}

//=====================================================================

void CRestoreInfo::AddSection(CString sName, CString sVersion)
{
	// Declare variables
	bool bFound = false;
	SectionInfo secInfo;
	
	// Check if the section isn't already added to the list
	for (int i = 0; i < m_iSectionCount; i++)
	{
		if (m_arrSections[i].sName == sName)
			bFound = true;
	}

	// If section is not found in the list
	if (!bFound)
	{
		// Prepare data
		secInfo.sName = sName;
		secInfo.sVersion = sVersion;

		// Add to list
		m_arrSections[m_iSectionCount++] = secInfo;
	}
}

//=====================================================================

int CRestoreInfo::GetSectionCount()
{
	// Return value
	return m_iSectionCount;
}

//=====================================================================

SectionInfo CRestoreInfo::GetSection(int iIndex)
{
	// Return value
	return m_arrSections[iIndex];
}

//=====================================================================

bool CRestoreInfo::RetrieveInformationFromRollback()
{
	// Declare variables
	CRollbackInfo * pRollbackInfo = CRollbackInfo::Instance();
	CSections * pSections = CSections::Instance();
	CSettings * pSettings = CSettings::Instance();
	SectionInfo sectionInfo;
	CRestoreActionBase * pAction;
	int i;

	// Clean up old information
	CleanUp();

	// Get general version
	m_sVersion = pSettings->GetAppVersion();

	// Get sections
	for (i = 0; i < pSections->GetSectionCount(); i++)
	{
		// Get data
		sectionInfo.sName = pSections->GetSectionInfo(i).sName;
		sectionInfo.sVersion = pSections->GetSectionInfo(i).sVersion;

		// Add to array
		m_arrSections[m_iSectionCount++] = sectionInfo;
	}

	// Get rollback actions
	for (i = 0; i < pRollbackInfo->GetActionCount(); i++)
	{
		// Set action to NULL
		pAction = NULL;

		// Get data
		if (pRollbackInfo->GetAction(i)->GetType() == ROLLBACKACTION_COPY)
		{
			// Copy action
			CRollbackActionCopy * pCopy = (CRollbackActionCopy *) pRollbackInfo->GetAction(i);
			CString sOldLocation, sNewLocation;
			
			// Get data
			sOldLocation = pCopy->GetOldLocation();
			sNewLocation = pCopy->GetNewLocation();

			// Create action
			pAction = new CRestoreActionCopy(sOldLocation, sNewLocation);
		}

		if (pRollbackInfo->GetAction(i)->GetType() == ROLLBACKACTION_DELETE)
		{
			// Delete action
			CRollbackActionDelete * pDelete = (CRollbackActionDelete *) pRollbackInfo->GetAction(i);
			CString sLocation;
			
			// Get data
			sLocation = pDelete->GetLocation();

			// Create action
			pAction = new CRestoreActionDelete(sLocation);
		}

		if (pRollbackInfo->GetAction(i)->GetType() == ROLLBACKACTION_REGISTRY)
		{
			// Registry action
			CRollbackActionRegistry * pRegistry = (CRollbackActionRegistry *) pRollbackInfo->GetAction(i);
			CString sKey, sValue;
			
			// Get data
			sKey = pRegistry->GetKey();
			sValue = pRegistry->GetValue();

			// Create action
			pAction = new CRestoreActionRegistry(sKey, sValue);
		}

		if (pRollbackInfo->GetAction(i)->GetType() == ROLLBACKACTION_UNREGISTER)
		{
			// Unregister action
			CRollbackActionUnregister * pUnregister = (CRollbackActionUnregister *) pRollbackInfo->GetAction(i);
			CString sFile;
			
			// Get data
			sFile = pUnregister->GetFile();

			// Create action
			pAction = new CRestoreActionUnregister(sFile);
		}

		// If action is valid, add it
		if (pAction != NULL)
		{
			// Add to array
			m_arrRestoreActions[m_iRestoreActionCount++] = pAction;
		}
	}

	// Return value
	return true;
}

//=====================================================================

bool CRestoreInfo::WriteToFile(CString sLocation)
{
	// Declare variables
	CString sXML = _T(""), sTemp;
	CStdioFile * pFile;
	int i;

	// Add opening
	sTemp.Format(_T("<RESTOREINFO version=\"%s\">\r\n"), m_sVersion);
	sXML += sTemp;

	// Write sections
	sXML += _T("  <SECTIONS>\r\n");
    for (i = 0; i < m_iSectionCount; i++)
	{
		sTemp.Format(_T("    <SECTION name=\"%s\" version=\"%s\" />\r\n"),
			m_arrSections[i].sName, m_arrSections[i].sVersion);
		sXML += sTemp;
	}
	sXML += _T("  </SECTIONS>\r\n");

	// Write actions
	sXML += _T("  <ACTIONS>\r\n");
	for (i = 0; i < m_iRestoreActionCount; i++)
	{
		sXML += m_arrRestoreActions[i]->GetXmlOutput();
	}
	sXML += _T("  </ACTIONS>\r\n");

	// Add ending
	sXML += _T("</RESTOREINFO>");

	try
	{
		// Create file
		pFile = new CStdioFile(sLocation, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);

		// Write first part so the file is unicode
		TCHAR bom = (TCHAR)0xFEFF;
		pFile->Write(&bom, sizeof(TCHAR));

		// Write data to file
		pFile->Write(sXML.GetBuffer(sXML.GetLength()), sXML.GetLength() * sizeof(TCHAR));

		// Close & clean up file
		pFile->Close();
		delete pFile;
	}
	catch (CException * pEx)
	{	
		// Delete exception
		pEx->Delete();

		// Return false
		return false;
	}

	// Return value
	return true;
}

//=====================================================================

bool CRestoreInfo::ReadFromFile(CString sLocation)
{
	// Declare variables
	CMarkup xml;
	CRestoreActionBase * pAction;
	SectionInfo sectionInfo;

	// Clean up old information
	CleanUp();

	// Read xml file into memory
	xml.SetDoc(XML_to_CString(sLocation));

	// Get version
	if (!xml.FindElem(_T("RESTOREINFO")))
		return false;
	m_sVersion = xml.GetAttrib(_T("version"));

	// Jump into element
	xml.IntoElem();

	// Read sections
	if (xml.FindElem(_T("SECTIONS")))
	{
		// Jump into element
		xml.IntoElem();

		// As long as we can find sections
		while (xml.FindElem(_T("SECTION")))
		{
			// Clean up object
			sectionInfo.sName = _T("");
			sectionInfo.sVersion = _T("");

			// Get all attributes
			sectionInfo.sName = xml.GetAttrib(_T("name"));
			sectionInfo.sVersion = xml.GetAttrib(_T("version"));

			// Add to array
			m_arrSections[m_iSectionCount++] = sectionInfo;
		}
			
		// Jump out of element
		xml.OutOfElem();
	}

	// Reset read pointer
	xml.ResetMainPos();

	// Read actions
	if (xml.FindElem(_T("ACTIONS")))
	{
		// Jump into element
		xml.IntoElem();

		// While we can find actions
		while (xml.FindElem(_T("ACTION")))
		{
			// Reset pointer to	NULL
			pAction = NULL;

			// Check type
			if (xml.GetAttrib(_T("type")) == _T("copy"))
			{
				// Copy action
				CString sOldLocation, sNewLocation;

				// Get all attributes
				sOldLocation = xml.GetAttrib(_T("old"));
				sNewLocation = xml.GetAttrib(_T("new"));

				// Create action
				pAction = new CRestoreActionCopy(sOldLocation, sNewLocation);
			}

			if (xml.GetAttrib(_T("type")) == _T("delete"))
			{
				// Delete action
				CString sLocation;

				// Get all attributes
				sLocation = xml.GetAttrib(_T("location"));

				// Create action
				pAction = new CRestoreActionDelete(sLocation);
			}

			if (xml.GetAttrib(_T("type")) == _T("registry"))
			{
				// Registry action
				CString sKey, sValue;

				// Get all attributes
				sKey = xml.GetAttrib(_T("key"));
				sValue = xml.GetAttrib(_T("value"));

				// Create action
				pAction = new CRestoreActionRegistry(sKey, sValue);
			}

			if (xml.GetAttrib(_T("type")) == _T("unregister"))
			{
				// Unregister action
				CString sFile;

				// Get all attributes
				sFile = xml.GetAttrib(_T("file"));

				// Create action
				pAction = new CRestoreActionUnregister(sFile);
			}

			// Should we add action?
			if (pAction != NULL)
			{
				// Yes, add
				m_arrRestoreActions[m_iRestoreActionCount++] = pAction;
			}
		}

		// Jump out of element
		xml.OutOfElem();
	}

	// Return value
	return true;
}

//=====================================================================

void CRestoreInfo::CleanUp()
{
	// Delete all Restore actions
	for (int i = 0; i < m_iRestoreActionCount; i++)
	{
		// Delete object
		delete m_arrRestoreActions[i];
	}

	// Reset counters
	m_iRestoreActionCount = 0;
	m_iSectionCount = 0;
}

//*********************************************************************
// PRIVATE FUNCTIONS
//*********************************************************************

bool CRestoreInfo::IsValidActionCopy(CRestoreActionBase * pAction)
{
	// Declare variables
	CRestoreActionCopy * pTemp;
	bool bValid = true;

	// Get object
	CRestoreActionCopy * pCopy = (CRestoreActionCopy *)pAction;

	// Check if file is't already in to be copied
	for (int i = 0; i < GetActionCount(); i++)
	{
		if (GetAction(i)->GetType() == RESTOREACTION_COPY)
		{
			// Get temp object
			pTemp = (CRestoreActionCopy *)GetAction(i);

			// Check if file isn't already begin copied
			if (pCopy->GetNewLocation() == pTemp->GetNewLocation())
				bValid = false;
		}
	}

	// Return value
	return bValid;
}

//=====================================================================

bool CRestoreInfo::IsValidActionDelete(CRestoreActionBase * pAction)
{
	// Declare variables
	CRestoreActionDelete * pTemp;
	bool bValid = true;
	
	// Get object
	CRestoreActionDelete * pDelete = (CRestoreActionDelete *)pAction;
	
	// Check if file isn't already in to be deleted
	for (int i = 0; i < GetActionCount(); i++)
	{
		if (GetAction(i)->GetType() == RESTOREACTION_DELETE)
		{
			// Get temp object
			pTemp = (CRestoreActionDelete *)GetAction(i);
			
			// Check if file isn't already being deleted
			if (pDelete->GetLocation() == pTemp->GetLocation())
				bValid = false;
		}
	}
	
	// Return value
	return bValid;
}

//=====================================================================

CString CRestoreInfo::XML_to_CString(CString sFilename)
{
	// Declare variables
	CString sText, sNotes;
	CFile file;
	int iFileLength;
	unsigned char * pBuffer;

	// Open XML file
	if (!file.Open(sFilename, CFile::modeRead | CFile::shareDenyNone))
		return _T("");

	// Get file length
	iFileLength = (int)file.GetLength();

	// Allocate buffer for binary file data
	pBuffer = new unsigned char[iFileLength + 2];

	// Read file
	iFileLength = file.Read(pBuffer, iFileLength);

	// Close file
	file.Close();

	// Add \0 to string
	pBuffer[iFileLength] = _T('\0');
	pBuffer[iFileLength + 1] = _T('\0'); // in case 2-byte encoded

	// Windows Unicode file is detected if starts with FEFF
	if ((pBuffer[0] == 0xff) && (pBuffer[1] == 0xfe))
	{
		// Contains byte order mark, so assume wide char content
		// non _UNICODE builds should perform UCS-2 (wide char) to UTF-8 conversion here
		sText = (LPCWSTR)(&pBuffer[2]);
	}
	else
	{
		// _UNICODE builds should perform UTF-8 to UCS-2 (wide char) conversion here
		sText = (LPCSTR)pBuffer;
	}

	// Release memory
	delete [] pBuffer;

	// If it is too short, assume it got truncated due to non-text content
	if (sText.GetLength() < iFileLength / 2 - 20)
	{
		return _T("");
	}

	// Return string
	return sText;
}